package com.yuews.codegenerator.generator;

import com.yuews.codegenerator.config.ConfigManager;
import com.yuews.codegenerator.model.TableInfo;
import com.yuews.codegenerator.template.TemplateEngine;
import freemarker.template.TemplateException;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成器 - 协调解析和模板引擎，生成完整代码
 */
public class CodeGenerator {
    private ConfigManager configManager;
    private TemplateEngine templateEngine;

    public CodeGenerator(ConfigManager configManager, TemplateEngine templateEngine) {
        this.configManager = configManager;
        this.templateEngine = templateEngine;
        // 初始化输出目录
        File outputDir = new File(configManager.getOutputPath());
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }
    }

    /**
     * 生成代码文件
     */
    public void generateCode(TableInfo tableInfo) throws IOException, TemplateException {
        String basePackage = configManager.getBasePackage();
        String outputPath = configManager.getOutputPath();
        
        // 构建包路径
        String packagePath = basePackage.replace('.', '/');
        
        // 准备模板数据
        Map<String, Object> data = prepareTemplateData(tableInfo);
        
        // 生成实体类
        generateEntity(tableInfo, data, outputPath, packagePath);
        
        // 生成Mapper接口
        generateMapper(tableInfo, data, outputPath, packagePath);
        
        // 生成XML映射文件
        generateXml(tableInfo, data, outputPath, packagePath);
        
        // 生成Service接口
        generateService(tableInfo, data, outputPath, packagePath);
        
        // 生成Service实现类
        generateServiceImpl(tableInfo, data, outputPath, packagePath);
        
        // 生成Controller（如果配置了）
        if (configManager.shouldGenerateController()) {
            generateController(tableInfo, data, outputPath, packagePath);
        }
    }

    /**
     * 准备模板数据
     */
    private Map<String, Object> prepareTemplateData(TableInfo tableInfo) {
        Map<String, Object> data = new HashMap<>();
        data.put("tableInfo", tableInfo);
        data.put("basePackage", configManager.getBasePackage());
        data.put("entityPackage", configManager.getBasePackage() + ".entity");
        data.put("mapperPackage", configManager.getBasePackage() + ".mapper");
        data.put("servicePackage", configManager.getBasePackage() + ".service");
        data.put("serviceImplPackage", configManager.getBasePackage() + ".service.impl");
        data.put("controllerPackage", configManager.getBasePackage() + ".controller");
        data.put("date", new java.util.Date());
        return data;
    }

    /**
     * 生成实体类
     */
    private void generateEntity(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        String entityDir = outputPath + File.separator + packagePath + File.separator + "entity";
        String entityFile = entityDir + File.separator + tableInfo.getEntityName() + ".java";
        generateFile(entityFile, configManager.getEntityTemplate(), data);
    }

    /**
     * 生成Mapper接口
     */
    private void generateMapper(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        String mapperDir = outputPath + File.separator + packagePath + File.separator + "mapper";
        String mapperFile = mapperDir + File.separator + tableInfo.getEntityName() + "Mapper.java";
        generateFile(mapperFile, configManager.getMapperTemplate(), data);
    }

    /**
     * 生成XML映射文件
     */
    private void generateXml(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        // XML文件通常放在resources目录下
        String xmlDir = outputPath.replace("java", "resources") + File.separator + packagePath + File.separator + "mapper";
        String xmlFile = xmlDir + File.separator + tableInfo.getEntityName() + "Mapper.xml";
        generateFile(xmlFile, configManager.getXmlTemplate(), data);
    }

    /**
     * 生成Service接口
     */
    private void generateService(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        String serviceDir = outputPath + File.separator + packagePath + File.separator + "service";
        String serviceFile = serviceDir + File.separator + tableInfo.getEntityName() + "Service.java";
        generateFile(serviceFile, configManager.getServiceTemplate(), data);
    }

    /**
     * 生成Service实现类
     */
    private void generateServiceImpl(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        String serviceImplDir = outputPath + File.separator + packagePath + File.separator + "service" + File.separator + "impl";
        String serviceImplFile = serviceImplDir + File.separator + tableInfo.getEntityName() + "ServiceImpl.java";
        generateFile(serviceImplFile, configManager.getServiceImplTemplate(), data);
    }

    /**
     * 生成Controller
     */
    private void generateController(TableInfo tableInfo, Map<String, Object> data, String outputPath, String packagePath) 
            throws IOException, TemplateException {
        String controllerDir = outputPath + File.separator + packagePath + File.separator + "controller";
        String controllerFile = controllerDir + File.separator + tableInfo.getEntityName() + "Controller.java";
        generateFile(controllerFile, configManager.getControllerTemplate(), data);
    }

    /**
     * 生成文件
     */
    private void generateFile(String filePath, String templateName, Map<String, Object> data) 
            throws IOException, TemplateException {
        // 创建目录
        Path path = Paths.get(filePath);
        Files.createDirectories(path.getParent());
        
        // 检查是否覆盖现有文件
        File file = path.toFile();
        if (file.exists() && !configManager.isOverwriteExisting()) {
            System.out.println("文件已存在，跳过生成: " + filePath);
            return;
        }
        
        // 渲染模板并写入文件
        String content = templateEngine.renderTemplate(templateName, data);
        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(file), StandardCharsets.UTF_8))) {
            writer.write(content);
        }
        
        System.out.println("生成文件: " + filePath);
    }
}